﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using ITAP.Core.Calculations;
using ITAP.Core.Modelling.Primitives;
using ITAP.Core.Modelling;

namespace ITAP.ContourBuilder.Components
{
    public enum TextRenderType
    {
        UseScreenTextSize,
        UseModelTextSize
    }

    [Serializable]
    public class ContourText : ContourComponent, ICommentSource
    {
        public virtual IEnumerable<IEndedContourComponent> CommentLines
        {
            get
            {
                List<IEndedContourComponent> result = new List<IEndedContourComponent>();
                foreach (IContourComponent connectedComponent in this.connectedComponents)
                    if (connectedComponent is ContourCommentLine)
                        result.Add(connectedComponent as IEndedContourComponent);

                return result;
            }
        }

        private TextRenderType textType = TextRenderType.UseModelTextSize;

        public TextRenderType TextType
        {
            get { return textType; }
            set { textType = value; }
        }

        internal SizeF StringSizeFromRender = SizeF.Empty;

        public override bool IsPrimitiveDependsOnDisplayParameters
        {
            get
            {
                return true;
            }
        }
        public ContourText(string text)
            : base()
        {
            this.text = text;
        }

        private string text;

        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        private Font font;

        public Font Font
        {
            get { return font; }
            set { font = value; }
        }

        private Color fontColor;

        public Color FontColor
        {
            get { return fontColor; }
            set { fontColor = value; }
        }

        private ModelPoint position = new ModelPoint();

        public override ModelPoint Position
        {
            get { return position; }
        }

        public override void AcceptVisitor(IContourVisitor visitor)
        {
            visitor.Visit(this);
        }

        public override void MoveWithOffset(ModelVector offset)
        {
            this.position = ModelCalculations.GetOffsetPoint(this.position, offset);
        }

        public override void MoveTo(ModelPoint destination)
        {
            this.position = destination.Clone() as ModelPoint;
        }

        public override bool CanSelectByPoint(ModelPoint point)
        {
            RectangleF rect = this.BoundingBox;
            PointF floatPoint = new PointF((float)point.X, (float)point.Y);
            if (rect.Contains(floatPoint))
                return true;
            else
                return false;
        }
        public override RectangleF BoundingBox
        {
            get
            {
                RectangleF rect;
                if (this.textType == TextRenderType.UseScreenTextSize)
                {
                    float modelWidth = coordinateConverter.ScreenMeasureToModelMeasure(this.StringSizeFromRender.Width, screenWidth, screenHeight, modelRectangle);
                    float modelHeight = coordinateConverter.ScreenMeasureToModelMeasure(this.StringSizeFromRender.Height, screenWidth, screenHeight, modelRectangle);
                    rect = new RectangleF((float)this.position.X, (float)this.position.Y - modelHeight, modelWidth, modelHeight);
                }
                else
                {
                    float modelWidth = this.StringSizeFromRender.Width * (float)GlobalData.FontSizeToScreenSizeFactor;
                    float modelHeight = this.StringSizeFromRender.Height * (float)GlobalData.FontSizeToScreenSizeFactor;
                    rect = new RectangleF((float)this.position.X, (float)this.position.Y - modelHeight, modelWidth, modelHeight);
                }
                return rect;
            }
        }

        #region IComment Members

        public virtual ModelPoint GetNearestCommentPoint(ModelPoint point)
        {
            RectangleF bbox = this.BoundingBox;
            ModelPoint leftPoint = new ModelPoint(bbox.X, bbox.Y);
            ModelPoint rightPoint = new ModelPoint(bbox.X + bbox.Width, bbox.Y);
            if (ModelCalculations.GetDistance(point, leftPoint) < ModelCalculations.GetDistance(point, rightPoint))
                return leftPoint;
            else
                return rightPoint;
        }

        #endregion

        public override IContourComponent ConnectToEnded(IEndedContourComponent component, EndType endToConnect)
        {
            return this.ConnectTo(component);
        }

        public override void Visit(ContourCommentLine commentLine)
        {
            RectangleF bbox = this.BoundingBox;
            PointF startPoint = new PointF((float)commentLine.StartPoint.X, (float)commentLine.StartPoint.Y);
            PointF endPoint = new PointF((float)commentLine.EndPoint.X, (float)commentLine.EndPoint.Y);
            if(bbox.Contains(startPoint))
            {
                ContourConnectionProvider.Connect(commentLine, this, EndType.Start);
                this.componentsInTolerance.Add(commentLine);
            }
            else if(bbox.Contains(endPoint))
            {
                ContourConnectionProvider.Connect(commentLine, this, EndType.End);
                this.componentsInTolerance.Add(commentLine);
            }
        }
        
        public override bool HasBoundingBox
        {
            get
            {
                return false;
            }
            set
            {
            }
        }
    }
}
